package com.hsfw.pmauthzuul.service.impl;

import com.hsfw.dbmodule.dao.LoginDao;
import com.hsfw.dbmodule.entity.Role;
import com.hsfw.dbmodule.entity.UserDetail;
import com.hsfw.dbmodule.entity.UserToken;
import com.hsfw.dbmodule.utils.BaseResponse;
import com.hsfw.dbmodule.utils.JWTUtil;
import com.hsfw.dbmodule.utils.ResponseCode;
import com.hsfw.pmauthzuul.exception.CustomException;
import com.hsfw.pmauthzuul.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;

/**
 * Created by RAZR on 16:26 2019/3/22.
 */
@Service
public class AuthServiceImpl implements AuthService {
    private final AuthenticationManager authenticationManager;
    private final UserDetailsService userDetailsService;
    private final JWTUtil jwtUtil;
    private final LoginDao loginDao;

    @Value("${JWT.tokenHead}")
    private String tokenHead;

    @Autowired
    public AuthServiceImpl(AuthenticationManager authenticationManager,
                           @Qualifier("UserDetailsServicelmpl") UserDetailsServiceImpl userDetailsService,
                           JWTUtil jwtUtil, LoginDao loginDao) {
        this.authenticationManager = authenticationManager;
        this.userDetailsService = userDetailsService;
        this.jwtUtil = jwtUtil;
        this.loginDao = loginDao;
    }

    @Override
    public UserToken login(String account, String password) {
        UserDetail userInfo;
        Role role;
        //用户验证
        final Authentication authentication = authenticate(account, password);
        //存储认证信息
        SecurityContextHolder.getContext().setAuthentication(authentication);
        //生成token
        final UserDetail ud = (UserDetail) authentication.getPrincipal();
        final String token = jwtUtil.generateAccessToken(ud);
        //存储token
        jwtUtil.putToken(account, token);
        return new UserToken(token, ud);

    }

    @Override
    public UserDetail register(UserDetail userDetail) {
        final String account = userDetail.getAccount();
        UserDetail userInfo;
        if (loginDao.findUserByAccountAllStatus(account).size() != 0) {
            throw new CustomException(BaseResponse.buildResponse().setCode(ResponseCode.BAD_REQUEST, "用户账户已存在").build());
        }
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        final String rawPassword = userDetail.getPassword();
        userDetail.setPwd(encoder.encode(rawPassword));
        loginDao.saveUserInfo(userDetail);
        userInfo = loginDao.findUserByAccountAllStatus(userDetail.getAccount()).get(0);
        String roleId = String.valueOf(userDetail.getRole().getRoleCode());
        //权限信息表暂未补充
//        Role role = loginDao.findRoleByRoleId(roleId);
//        userInfo.setRole(role);
//        loginDao.saveUserRoleLink(String.valueOf(userInfo.getId()), roleId, userInfo.getRole().getRoleCode());
        return userDetail;
    }

    @Override
    public UserDetail updateUserInfo(UserDetail userDetail) {
        final String account = userDetail.getAccount();
        if (loginDao.findUserByAccountAllStatus(account).size() == 0) {
            throw new CustomException(BaseResponse.buildResponse().setCode(ResponseCode.BAD_REQUEST, "用户不存在").build());
        }
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        final String rawPassword = userDetail.getPassword();
        userDetail.setPwd(encoder.encode(rawPassword));
        loginDao.updateUserInfo(userDetail);
        //权限信息未创建
//        if (userDetail.getRole() != null) {
//            String roleId = String.valueOf(userDetail.getRole().getId());
//            Role role = loginDao.findRoleByRoleId(roleId);
//            userDetail.setRole(role);
//            loginDao.saveUserRoleLink(String.valueOf(userDetail.getId()), roleId, userDetail.getRole().getRoleCode());
//        }
        return userDetail;
    }

    @Override
    public void logout(HttpServletRequest request) {
        jwtUtil.deleteToken(jwtUtil.getUserFromToken(request).getAccount());
    }

    @Override
    public UserToken refresh(String oldToken) {
        String token = oldToken.substring(tokenHead.length());
        String username = jwtUtil.getUsernameFromToken(token);
        UserDetail userDetail = (UserDetail) userDetailsService.loadUserByUsername(username);
//        if (jwtUtil.canTokenBeRefreshed(token, userDetail.getLastPasswordResetDate())) {
//            token = jwtUtil.refreshToken(token);
//            return new UserToken(token, userDetail);
//        }
        return null;
    }

    @Override
    public UserDetail getUserByToken(String token) {
        token = token.substring(tokenHead.length());
        return jwtUtil.getUserFromToken(token);
    }

    private Authentication authenticate(String username, String password) {
        try {
            //该方法会去调用userDetailsService.loadUserByUsername()去验证用户名和密码，如果正确，则存储该用户名密码到“security 的 context中”
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
        } catch (DisabledException | BadCredentialsException e) {
            throw new CustomException(BaseResponse.buildResponse().setCode(ResponseCode.LOGIN_ERROR, e.getMessage()).build());
        }
    }
}
